package com.bestcem.xm.member.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.ObjectId;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.bp.xm.user.grpc.v1.services.Organization;
import com.bestcem.bp.xm.user.grpc.v1.services.User;
import com.bestcem.xm.common.core.constant.ErrorCodes;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.CommonUtil;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.common.core.uitls.EnumUtil;
import com.bestcem.xm.common.core.uitls.StringUtil;
import com.bestcem.xm.componet.redis.service.RedisService;
import com.bestcem.xm.label.dao.LabelDao;
import com.bestcem.xm.label.dao.LabelGroupDao;
import com.bestcem.xm.label.dao.LabelValueDao;
import com.bestcem.xm.label.entity.pojo.LabelDO;
import com.bestcem.xm.label.entity.pojo.LabelGroupDO;
import com.bestcem.xm.label.entity.pojo.LabelValueDO;
import com.bestcem.xm.member.dao.DisplayRangeDao;
import com.bestcem.xm.member.dao.GroupDao;
import com.bestcem.xm.member.dao.MemberDao;
import com.bestcem.xm.member.entity.pojo.DisplayRangeDO;
import com.bestcem.xm.member.entity.pojo.MemberDO;
import com.bestcem.xm.member.enums.*;
import com.bestcem.xm.member.grpc.client.SurveyClient;
import com.bestcem.xm.member.grpc.client.UserClient;
import com.bestcem.xm.member.grpc.client.XmMemberClient;
import com.bestcem.xm.member.grpc.client.dto.QdesQuestionDTO;
import com.bestcem.xm.member.grpc.client.dto.QdesQuestionOptionDTO;
import com.bestcem.xm.member.mq.message.*;
import com.bestcem.xm.member.service.*;
import com.bestcem.xm.member.service.cache.CacheMemberService;
import com.bestcem.xm.member.service.dto.OrganizationDTO;
import com.bestcem.xm.member.service.mq.send.MemberMessageSendService;
import com.bestcem.xm.member.service.param.AddFootprintParam;
import com.bestcem.xm.member.util.CheckUtil;
import com.bestcem.xm.member.util.MemberUtil;
import com.bestcem.xm.member.util.ValidationUtil;
import com.bestcem.xm.survey.grpc.v1.services.Respondent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author ming.xue <ming.xue@idiaoyan.com>
 * @desc 联系人默认消息处理器
 * @date 2021-08-19
 */
@Slf4j
@Service("memberMqHandler")
public class MemberMqHandlerImpl implements MemberMqHandler {
    private static final Logger EMAIL_LOG = LoggerFactory.getLogger("EmailErrorLog");

    /**
     * 足迹点服务
     */
    @Autowired
    private FootprintService footprintService;

    @Resource
    private DisplayRangeDao displayRangeDao;

    @Resource
    private LabelGroupDao labelGroupDao;

    @Resource
    private LabelDao labelDao;

    @Resource
    private LabelValueDao labelValueDao;

    @Resource
    private SyncRuleService syncRuleService;

    @Resource
    private MemberDao memberDao;

    @Resource
    private SequenceService sequenceService;

    @Resource
    private MemberUtil memberUtil;

    @Resource
    private SurveyClient surveyClient;

    @Resource
    private CacheMemberService cacheMemberService;

    @Resource
    private UserClient userClient;

//    @Resource
//    private RabbitMessageSender rabbitMessageSender;

    @Resource
    private RedisService redisService;

    @Resource
    private SourceCardService sourceCardService;
//
//    @Autowired
//    private RabbitMqConstantConfig rabbitMqConstantConfig;

    @Resource
    private XmMemberClient xmMemberClient;

    @Resource
    private GroupService groupService;

    @Resource
    private GroupDao groupDao;
    @Autowired
    private MemberMessageSendService memberMessageSendService;

    /**
     * 默认标签组名称
     */
    private static final List<String> DEFAULT_LABEL_GROUP_NAME = Arrays.asList("答卷行为", "人口属性", "交易行为", "态度偏好");

    /**
     * 默认标签名称
     */
    private static final List<String> DEFAULT_LABEL_NAME = Arrays.asList("答题率", "答题完成率");

    /**
     * 默认标签值
     */
    private static final List<String> DEFAULT_LABEL_VALUE = Arrays.asList("高", "中", "低");

    /**
     * 默认答题率 答题完成率条件
     */
    private static final Map<String, Map<String, String>> DEFAULT_CONDITION = new HashMap<>(1 << 2);

    static {
        Map<String, String> answerRate = new HashMap<>(1 << 3);
        answerRate.put("高", "{\"rule\": \"$and\", \"filters\": [{\"source\": \"computes\", \"name\": \"receive_total_count\", \"value\": 2, \"type\": \"number\", \"operator\": \"$gte\"}, {\"source\": \"computes\", \"name\": \"answer_rate\", \"value\": 0.3, \"type\": \"number\", \"operator\": \"$gte\"}]}");
        answerRate.put("中", "{\"rule\": \"$and\", \"filters\": [{\"source\": \"computes\", \"name\": \"receive_total_count\", \"value\": 2, \"type\": \"number\", \"operator\": \"$gte\"}, {\"source\": \"computes\", \"name\": \"answer_rate\", \"value\": [0.1, 0.3], \"type\": \"number\", \"operator\": \"$range\", \"detail\": {\"left_open\": false, \"right_open\": true}}]}");
        answerRate.put("低", "{\"rule\": \"$and\", \"filters\": [{\"source\": \"computes\", \"name\": \"receive_total_count\", \"value\": 2, \"type\": \"number\", \"operator\": \"$gte\"}, {\"source\": \"computes\", \"name\": \"answer_rate\", \"value\": 0.1, \"type\": \"number\", \"operator\": \"$lt\"}]}");
        DEFAULT_CONDITION.put("答题率", answerRate);

        Map<String, String> answerFinishRate = new HashMap<>(1 << 3);
        answerFinishRate.put("高", "{\"rule\": \"$and\", \"filters\": [{\"source\": \"computes\", \"name\": \"start_answer_count\", \"value\": 2, \"type\": \"number\", \"operator\": \"$gte\"}, {\"source\": \"computes\", \"name\": \"submit_rate\", \"value\": 0.6, \"type\": \"number\", \"operator\": \"$gte\"}]}");
        answerFinishRate.put("中", "{\"rule\": \"$and\", \"filters\": [{\"source\": \"computes\", \"name\": \"start_answer_count\", \"value\": 2, \"type\": \"number\", \"operator\": \"$gte\"}, {\"source\": \"computes\", \"name\": \"submit_rate\", \"value\": [0.3, 0.6], \"type\": \"number\", \"operator\": \"$range\", \"detail\": {\"left_open\": false, \"right_open\": true}}]}");
        answerFinishRate.put("低", "{\"rule\": \"$and\", \"filters\": [{\"source\": \"computes\", \"name\": \"start_answer_count\", \"value\": 2, \"type\": \"number\", \"operator\": \"$gte\"}, {\"source\": \"computes\", \"name\": \"submit_rate\", \"value\": 0.3, \"type\": \"number\", \"operator\": \"$lt\"}]}");
        DEFAULT_CONDITION.put("答题完成率", answerFinishRate);
    }

    private static Map<String, String> WX_SEX_MAP = new HashMap<String, String>() {{
        put("1", "男");
        put("2", "女");
    }};

    /**
     * 保存联系人足迹
     *
     * @param message
     * @return 处理结果 true: 成功 false: 失败
     */
    @Override
    public boolean saveFootprint(FootprintMessage message) {
        if (message == null) {
            log.error("接收足迹点消息失败, 消息为空");
            return false;
        }

        if (log.isDebugEnabled()) {
            log.debug("[{}] 接收足迹点消息: message: {}", Thread.currentThread().getName(), message);
        }

        if (ObjectUtil.isNotEmpty(message.getIsCopyDemo()) && message.getIsCopyDemo()) {
            if (log.isInfoEnabled()) {
                log.info("{} 是demo数据，不生成足迹点", message);
            }
            return false;
        }

        AddFootprintParam param = null;
        ServiceResult<String> result = null;
        Set<ConstraintViolation<Object>> violations = null;
        try {
            // 验证参数
            param = this.toAddFootprintParam(message);
            violations = ValidationUtil.validateParam(param);
            if (!CollectionUtils.isEmpty(violations)) {
                log.error("接收足迹点消息失败, 参数校验失败, message: {}, param: {}, violations: {}",
                        message, param, violations);
                return false;
            }

            // 新增足迹点
            result = footprintService.addFootprint(param);
            if (result.isSuccess()) {
                return true;
            } else {
                log.error("接收足迹点消息失败, 新增足迹点失败, message: {}, param: {}, result: {}",
                        message, param, result);

                // 需要重试
                if (StringUtils.equals(result.getErrorCode(), ErrorCodes.B0002)) {
                    return false;
                }
            }
        } catch (Exception e) {
            log.error("接收足迹点消息失败, 原因未知, message: {}, param: {}, violations: {}, result: {}",
                    message, param, violations, result, e);
            return false;
        }
        return false;
    }

    @Override
    public boolean createDefaultLabelGroup(OrgCreatedMessage message) {
        if (message == null) {
            log.error("接收机构创建消息失败, 消息为空");
            return false;
        }

        if (log.isDebugEnabled()) {
            log.debug("[{}] 接收机构创建消息: message: {}", Thread.currentThread().getName(), message);
        }

        String orgId = message.getId();
        try {
            // 循环处理逻辑
            for (int i = 0; i < DEFAULT_LABEL_GROUP_NAME.size(); i++) {
                String labelGroupName = DEFAULT_LABEL_GROUP_NAME.get(i);

                boolean isExists = labelGroupDao.containsDuplicate(orgId, labelGroupName);
                // 查看对应机构的数据是否存在，进行幂等控制(同一个公司创建只会有一条msg，不会有高并发情况)
                if (isExists) {
                    continue;
                }

                // 新增标签组
                LabelGroupDO labelGroup = new LabelGroupDO();
                labelGroup.setOrgId(orgId);
                labelGroup.setName(labelGroupName);
                labelGroup.setMemberType(MemberTypeEnum.INDIVIDUAL.getIndex());
                labelGroup.setSeq(i);
                labelGroup.setCreateTime(DateUtil.getCommonDate());
                labelGroup.setUpdateTime(labelGroup.getCreateTime());
                labelGroupDao.insert(labelGroup);
            }
            // 获取答卷行为信息
            String labelGroupName = DEFAULT_LABEL_GROUP_NAME.get(0);
            LabelGroupDO labelGroup = labelGroupDao.find(orgId, labelGroupName);

            if (Objects.isNull(labelGroup)) {
                log.error("未知错误导致，答卷行为的标签组查询结果为空 orgId: {}", orgId);
                return false;
            }

            for (String labelName : DEFAULT_LABEL_NAME) {
                // 新增或更新标签
                LabelDO label = new LabelDO();
                label.setName(labelName);
                label.setLabelGroupId(labelGroup.getId());
                label.setOrgId(orgId);
                label.setManual(0);
                label.setAuto(1);

                label = labelDao.insertOrReplace(label);

                Map<String, String> rateMap = DEFAULT_CONDITION.get(labelName);
                for (int i = 0; i < DEFAULT_LABEL_VALUE.size(); i++) {
                    String value = DEFAULT_LABEL_VALUE.get(i);

                    // 新增或更新标签值
                    LabelValueDO labelValue = new LabelValueDO();
                    labelValue.setValue(value);
                    labelValue.setLabelGroupId(label.getLabelGroupId());
                    labelValue.setLabelId(label.getLabelId());
                    labelValue.setOrgId(orgId);
                    labelValue.setAuto(label.getAuto());
                    labelValue.setManual(label.getManual());

                    labelValue.setSeq(i);
                    labelValue.setLabelGroupName(labelGroupName);
                    labelValue.setLabelName(label.getName());
                    labelValue.setMemberType(MemberTypeEnum.INDIVIDUAL.getIndex());
                    if (Objects.nonNull(rateMap)) {
                        labelValue.setCondition(rateMap.get(value));
                    }

                    labelValueDao.insertOrReplace(labelValue);
                }
            }

            return true;
        } catch (Exception e) {
            log.error("接收机构创建消息，创建默认标签分组及标签失败, message: {} e: {} ", message, e);
        }
        return false;
    }

    @Override
    public boolean createMemberDisplayRange(OrgCreatedMessage message) {
        if (message == null) {
            log.error("接收机构创建消息失败, 消息为空");
            return false;
        }

        if (log.isDebugEnabled()) {
            log.debug("[{}] 接收机构创建消息: message: {}", Thread.currentThread().getName(), message);
        }
        String orgId = message.getId();

        try {
            // 循环处理逻辑
            for (MemberTypeEnum mType : MemberTypeEnum.values()) {
                // 跳过project
                if (mType.equals(MemberTypeEnum.PROJECT)) {
                    continue;
                }

                // 查看对应机构的数据是否存在，进行幂等控制(同一个公司创建只会有一条msg，不会有高并发情况)
                DisplayRangeDO displayRange = displayRangeDao.findByOrgAndMemberType(orgId, mType.getIndex());
                if (Objects.nonNull(displayRange)) {
                    if (log.isInfoEnabled()) {
                        log.info("展示范围已存在:{}", orgId);
                    }
                    continue;
                }

                // 新增展示范围
                DisplayRangeDO range = new DisplayRangeDO();
                range.setOrgId(orgId);
                range.setMemberType(mType.getIndex());
                range.setType(DisplayRangeTypeEnum.ALL.value());
                range.setCreateTime(DateUtil.getCommonDate());
                range.setUpdateTime(range.getCreateTime());

                displayRangeDao.create(range);
            }
            return true;
        } catch (Exception e) {
            log.error("接收机构创建消息，创建联系人可见范围失败, message: {} e: {}", message, e);
        }
        return false;
    }

    @Override
    public boolean createMemberByRespondentSubmit(RespondentDataMessage data) {
        if (ObjectUtil.isNotEmpty(data.getIsCopyDemo()) && data.getIsCopyDemo()) {
            log.info("{} 是demo数据 不生成联系人", JSONObject.toJSONString(data));
            return false;
        }

        // python即使在copy sample/solution的时候，也会发送 问卷同步联系人 的消息
        // 如果放行，那么最终会导致(问卷同步联系人的那部分)数据重复
        if (ObjectUtil.isNotEmpty(data.getIsCopy()) && data.getIsCopy()) {
            log.info("{} 已copy过该联系人 不生成联系人", JSONObject.toJSONString(data));
            return false;
        }

        if (log.isInfoEnabled()) {
            log.info(" 答卷消息为 {}", JSONObject.toJSONString(data));
        }
        // 获取项目id
        final String projectId = StrUtil.isEmpty(data.getProjectId()) ? "" : data.getProjectId();
        // 获取项目id
        String respondentId = data.getRespondentId();
        if (StrUtil.isEmpty(respondentId)) {
            respondentId = "";
        }
        // 获取版本
        Integer version = data.getVersion();

        // 获取数据状态
        Integer dataStatus = data.getDataStatus();
        if (ObjectUtil.isEmpty(dataStatus)) {
            dataStatus = 0;
        }
        // 获取答案
        JSONObject answer = data.getAnswers();

        if (ObjectUtil.isEmpty(answer)) {
            if (log.isInfoEnabled()) {
                log.info("respondentId {} 答案不存在 {} ", respondentId, JSONObject.toJSONString(data));
            }
            return false;
        }

        if (dataStatus == 0) {
            log.error("data_status=0,不能创建联系人");
            return false;
        }
        // 获取问卷的问题列表

        List<QdesQuestionDTO> qdesQuestionDTOS = cacheMemberService.getQuestionDTOS(projectId, version);

        Map<String, JSONArray> memberQids = getMemberQids(qdesQuestionDTOS);

        List<Object> mobile2 = getMemberInfo(answer, memberQids.get("mobile"));

        List<Object> email1 = getMemberInfo(answer, memberQids.get("email"));
        List<Object> name1 = getMemberInfo(answer, memberQids.get("name"));
        List<Object> age = getMemberInfo(answer, memberQids.get("age"));
        List<Object> gender1 = getMemberInfo(answer, memberQids.get("gender"));
        List<Object> address1 = getMemberInfo(answer, memberQids.get("address"));

        List<String> mobileList = new ArrayList<>();
        if (CollUtil.isNotEmpty(mobile2)) {
            if (log.isInfoEnabled()) {
                log.info("该用户手机号 {}", mobile2);
            }
            mobileList = mobile2.stream().map(String::valueOf).collect(Collectors.toList());
        }
        List<String> emailList = new ArrayList<>();
        if (CollUtil.isNotEmpty(email1)) {
            if (log.isInfoEnabled()) {
                log.info("该用户邮箱 {}", email1);
            }
            emailList = email1.stream().map(String::valueOf).collect(Collectors.toList());
        }
        List<String> nameList = new ArrayList<>();
        if (CollUtil.isNotEmpty(name1)) {
            if (log.isInfoEnabled()) {
                log.info("该用户姓名 {}", name1);
            }
            nameList = name1.stream().map(String::valueOf).collect(Collectors.toList());
        }
        List<Integer> ageList = new ArrayList<>();
        if (CollUtil.isNotEmpty(age)) {
            if (log.isInfoEnabled()) {
                log.info("该用户年龄 {}", age);
            }
            ageList = age.stream().map(a -> Integer.valueOf(String.valueOf(a))).collect(Collectors.toList());
        }
        List<String> genderList = new ArrayList<>();
        if (CollUtil.isNotEmpty(gender1)) {
            if (log.isInfoEnabled()) {
                log.info("该用户性别 {}", gender1);
            }
            genderList = gender1.stream().map(String::valueOf).collect(Collectors.toList());
        }
        List<String> addressList = new ArrayList<>();
        if (CollUtil.isNotEmpty(address1)) {
            if (log.isInfoEnabled()) {
                log.info("该用户地址 {}", address1);
            }
            addressList = address1.stream().map(String::valueOf).collect(Collectors.toList());
        }

        // 获取手机号
        String mobile = CollUtil.isNotEmpty(mobileList) ? mobileList.get(mobileList.size() - 1) : "";
        String email = CollUtil.isNotEmpty(emailList) ? emailList.get(emailList.size() - 1) : "";
        String name = CollUtil.isNotEmpty(nameList) ? nameList.get(nameList.size() - 1) : "";
        String gender = "";
        if (StrUtil.isNotBlank(email)) {
            // 校验规则
            ServiceResult<String> result = CheckUtil.checkEmailFormat(email);
            if (!result.isSuccess()) {
                log.error("【联系人】邮箱校验失败 {}", email);
                return false;
            }
        }

        if (CollUtil.isNotEmpty(genderList)) {
            gender = genderList.get(genderList.size() - 1);
            if (CollUtil.isNotEmpty(qdesQuestionDTOS)) {
                for (QdesQuestionDTO qdesQuestionDTO : qdesQuestionDTOS) {
                    String customQtype = qdesQuestionDTO.getCustomQtype();
                    if ("info_sex".equals(customQtype)) {
                        List<QdesQuestionOptionDTO> items = qdesQuestionDTO.getItems();
                        if (CollUtil.isNotEmpty(items)) {
                            for (QdesQuestionOptionDTO item : items) {
                                if (StrUtil.isNotEmpty(gender)) {
                                    if (Integer.valueOf(gender).equals(item.getGid())) {
                                        gender = item.getTitle();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        List<String> address = new ArrayList<>();
        if (CollUtil.isNotEmpty(addressList)) {
            addressList.forEach(item -> {
                address.add(item);
            });
        }
        String orgId = cacheMemberService.getCompanyId(projectId);

        log.info("orgId {}", orgId);
        // 判断联系人同步是否开启
        Integer syncRuleType = syncRuleService.get(orgId, MemberTypeEnum.INDIVIDUAL.getIndex());

        if (log.isInfoEnabled()) {
            log.info("需要同步的用户信息 {} {} {} {} {} {}", orgId, mobile, email, name, gender, address);
        }

        // 获取答卷，用来判断答卷中是否已经添加了联系人
        Respondent respondent = surveyClient.getRespondent(respondentId, projectId);
        if (log.isInfoEnabled()) {
            log.info("答卷信息 {} ", respondent.toString());
        }
        Boolean isSync = true;
        if (ObjectUtil.isNotEmpty(syncRuleType) && syncRuleType.equals(SyncTypeEnum.NEVER.getIndex())) {
            isSync = false;
        }

        // 获取组织信息
        OrganizationDTO dto = cacheMemberService.getOrganizationDTO(orgId);
        Integer mType = MemberTypeEnum.INDIVIDUAL.getIndex();
        Integer status = MemberStatusEnum.ACTIVATED.getIndex();

        MemberDO newMember = new MemberDO();
        newMember.setMemberType(mType);
        newMember.setStatus(status);
        newMember.setOrgId(orgId);
        newMember.setEmail(email);
        newMember.setName(name);
        newMember.setGender(gender);
        newMember.setAddress(JSONObject.toJSONString(address));
        newMember.setPhone(mobile);
        newMember.setAvatar(data.getWxAvatar());
        newMember.setNickname(data.getWxNickname());
        newMember.setUnionId(data.getWxUnionId());
        if (StrUtil.isNotEmpty(data.getWxAppId()) && StrUtil.isNotEmpty(data.getWxOpenId())) {
            newMember.setAppId(data.getWxAppId());
            newMember.setOpenId(data.getWxOpenId());
        }
        String wxSex = StrUtil.isEmpty(data.getWxSex()) ? "" : WX_SEX_MAP.getOrDefault(data.getWxSex(), "");
        if (StrUtil.isNotEmpty(mobile)) {
            handleMobileWithLock(newMember, isSync, dto, respondent, wxSex);
        } else if (StrUtil.isNotEmpty(email)) {
            handleEmailWithLock(newMember, isSync, dto, respondent, wxSex);
        } else if (StrUtil.isNotEmpty(data.getWxAppId()) && StrUtil.isNotEmpty(data.getWxOpenId())) {
            newMember.setAppId(data.getWxAppId());
            newMember.setOpenId(data.getWxOpenId());
            this.handleWechatWithLock(newMember, isSync, dto, respondent, wxSex);
        }
        return true;
    }

    /**
     * 监听创建用户
     * fixme 业务逻辑迁移至service层
     *
     * @param userMessage 请求参数
     */
    @Override
    public void createInnerMemberByCreateUser(UserMessage userMessage) throws Exception {
        if (userMessage == null) {
            throw new Exception("消息数据为空");
        }
        if (log.isInfoEnabled()) {
            log.info("账号创建的时候创建内部联系人----------{}", JSONObject.toJSONString(userMessage));
        }

        String userId = userMessage.getId();
        List<String> storeNameAndId = userMessage.getStoreNameAndId();

        User user = userClient.getUser(userId);
        if (user == null) {
            log.error("[XM]监听创建用户信息，查询用户信息失败");
            return;
        }

        // 创建联系人
        MemberDO innerMemeber = new MemberDO();
        innerMemeber.setId(StringUtil.getId());
        innerMemeber.setUserId(userId);
        innerMemeber.setOrgId(user.getOrgId());
        innerMemeber.setPhone(user.getPhone());
        innerMemeber.setEmail(user.getEmail());
        innerMemeber.setName(user.getName());
        innerMemeber.setEmployeeStatus(EmployeeStatusEnum.MEMBER_EMPLOYEE_STATUS_WORK.getIndex());
        innerMemeber.setMemberType(MemberTypeEnum.INTERIOR.getIndex());
        innerMemeber.setStatus(NewMemberStatusEnum.MEMBER_STATUS_ACTIVATED.getIndex());
        innerMemeber.setStoreId("");
        if (!CollectionUtils.isEmpty(storeNameAndId)) {
            innerMemeber.setStoreId(storeNameAndId.get(storeNameAndId.size() - 1));
        }

        // 缓存获取联系人序号

        String innerMemberNoKey = "member:memberNo." + innerMemeber.getOrgId();
        Object interior = redisService.hashGet(innerMemberNoKey, "INTERIOR");

        String memberNo = "";
        if (ObjectUtil.isNotEmpty(interior)) {
            memberNo = NumberUtil.decimalFormat("00000000", Integer.parseInt(String.valueOf(interior)) + 1);
        } else {
            memberNo = "00000001";
        }
        innerMemeber.setMemberNo("E" + memberNo);
        redisService.hashSet(innerMemberNoKey, "INTERIOR", memberNo);

        innerMemeber.setCreateTime(DateUtil.getCommonDate());
        innerMemeber.setUpdateTime(innerMemeber.getCreateTime());
        innerMemeber = memberDao.createInnerMemberByCreateUser(innerMemeber);
        log.info("[XM]同步创建内部联系人：{}", innerMemeber);

        // 发送创建联系人消息
        Organization organization = userClient.getOrganization(innerMemeber.getOrgId());
        if (organization == null) {
            log.error("[XM]查询企业信息失败：{}", innerMemeber.getOrgId());
            return;
        }

        MemberMessage memberMessage = MemberUtil.memberDoToMemberMessage(innerMemeber);
        memberMessage.setOrgCode(organization.getCode());
        memberMessage.setOrgName(organization.getName());
        memberMessage.setIdentityType(EmployeeStatusEnum.MEMBER_EMPLOYEE_STATUS_WORK.getName());
//        try {
//            rabbitMessageSender.sendMsg(rabbitMqConstantConfig.getAppFanoutExchange(),
//                    null,
//                    MemberMqConstant.MEMBER_CREATE,
//                    memberMessage);
//        } catch (JsonProcessingException e) {
//            log.error("[XM]创建联系人发送mq异常：{}", e.getMessage());
//        }
        //stream mq 2022/05/12
        memberMessageSendService.memberCreatedSend(memberMessage);
    }

    /**
     * 监听更新用户
     * fixme 业务逻辑迁移至service层
     *
     * @param userMessage 请求参数
     */
    @Override
    public void updateInnerMemberByUpdateUser(UserMessage userMessage) throws Exception {
        if (userMessage == null) {
            throw new Exception("消息数据为空");
        }
        if (log.isInfoEnabled()) {
            log.info("账号更新的时候更新内部联系人----------{}", JSONObject.toJSONString(userMessage));
        }

        String userId = userMessage.getId();
        List<String> storeNameAndId = userMessage.getStoreNameAndId();
        User user = userClient.getUser(userId);

        // 校验联系人是否存在
        MemberDO member = memberDao.findByUserId(user.getOrgId(), userId);
        if (member == null) {
            log.error("[XM]联系人不存在：{}", user);
            return;
        }

        // 更新联系人 (mobile、email、name、store)
        member.setId(member.getId());
        member.setPhone(user.getPhone());
        member.setEmail(user.getEmail());
        member.setName(user.getName());
        member.setStoreId("");
        if (!CollectionUtils.isEmpty(storeNameAndId)) {
            member.setStoreId(storeNameAndId.get(storeNameAndId.size() - 1));
        }
        member.setGroupSyncToken(null);
        memberDao.updateMember(member, false);
        log.info("[XM]更新创建内部联系人：{}", member);

        // 发送创建联系人消息
        Organization organization = userClient.getOrganization(member.getOrgId());
        if (organization == null) {
            log.error("[XM]查询企业信息失败：{}", member.getOrgId());
            return;
        }

        MemberMessage memberMessage = MemberUtil.memberDoToMemberMessage(member);
        memberMessage.setOrgCode(organization.getCode());
        memberMessage.setOrgName(organization.getName());
        EmployeeStatusEnum employeeStatusEnum = EnumUtil.getEnumByIndex(EmployeeStatusEnum.class, member.getEmployeeStatus());
        memberMessage.setIdentityType(employeeStatusEnum == null ? "" : employeeStatusEnum.getName());
//        try {
//            rabbitMessageSender.sendMsg(rabbitMqConstantConfig.getAppFanoutExchange(),
//                    null,
//                    MemberMqConstant.MEMBER_UPDATE,
//                    memberMessage);
//        } catch (JsonProcessingException e) {
//            log.error("[XM]更新联系人发送mq异常：{}", e.getMessage());
//        }
        //stream mq 2022/05/12
        memberMessageSendService.memberUpdatedSend(memberMessage);
    }

    /**
     * 类型转换
     *
     * @param message
     * @return
     */
    private AddFootprintParam toAddFootprintParam(FootprintMessage message) {
        AddFootprintParam param = new AddFootprintParam();
        if (message != null) {
            param.setOrgId(message.getOrgId());
            param.setMemberId(message.getMemberId());
            param.setType(message.getType());
            param.setSourceKey(message.getSourceKey());
            param.setContent(message.getContent());
            param.setFootprintTime(message.getFootprintTime());
        }

        return param;
    }

    private String getLockName(String orgId, String mobileOrEmail) {
        orgId = StringUtils.trimToEmpty(orgId);
        mobileOrEmail = StringUtils.trimToEmpty(mobileOrEmail);

        String rawKey = String.format("%s:%s", orgId, mobileOrEmail);
        return String.valueOf(CommonUtil.hash(rawKey) % 128);
    }

    /**
     * 处理手机问卷
     *
     * @param newMember
     * @param isSync
     * @param dto
     * @param respondent
     * @param wxSex
     */
    private void handleMobileWithLock(MemberDO newMember, Boolean isSync, OrganizationDTO dto,
                                      Respondent respondent, String wxSex) {
        String orgId = newMember.getOrgId();
        String mobile = newMember.getPhone();
        RLock lock = redisService.getLock(this.getLockName(orgId, mobile));
        try {
            lock.lock(30, TimeUnit.SECONDS);
            this.handleMobile(newMember, isSync, dto, respondent, wxSex);
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 处理微信问卷
     *
     * @param newMember
     * @param isSync
     * @param dto
     * @param respondent
     * @param wxSex
     */
    private void handleWechatWithLock(MemberDO newMember, Boolean isSync, OrganizationDTO dto,
                                      Respondent respondent, String wxSex) {
        String orgId = newMember.getOrgId();
        String appId = newMember.getAppId();
        String openId = newMember.getOpenId();
        RLock lock = redisService.getLock(this.getLockName(orgId, String.format("%s.%s", appId, openId)));
        try {
            lock.lock(30, TimeUnit.SECONDS);
            this.handleWechat(newMember, isSync, dto, respondent, wxSex);
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 处理邮件问卷
     *
     * @param newMember
     * @param isSync
     * @param dto
     * @param respondent
     * @param wxSex
     */
    private void handleEmailWithLock(MemberDO newMember, Boolean isSync, OrganizationDTO dto,
                                     Respondent respondent, String wxSex) {
        String orgId = newMember.getOrgId();
        String email = newMember.getEmail();
        RLock lock = redisService.getLock(this.getLockName(orgId, email));
        try {
            lock.lock(30, TimeUnit.SECONDS);
            this.handleEmail(newMember, isSync, dto, respondent, wxSex);
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 处理手机问卷
     *
     * @param newMember
     * @param isSync
     * @param dto
     * @param respondent
     * @param wxSex
     */
    private void handleMobile(MemberDO newMember, Boolean isSync, OrganizationDTO dto,
                              Respondent respondent, String wxSex) {
        String mobile = newMember.getPhone();
        String orgId = newMember.getOrgId();
        Integer mType = newMember.getMemberType();
        Integer status = newMember.getStatus();
        String email = newMember.getEmail();
        String name = newMember.getName();
        String gender = newMember.getGender();
        String address = newMember.getAddress();
        String openId = newMember.getOpenId();
        String appId = newMember.getAppId();
        String nickname = newMember.getNickname();
        String unionId = newMember.getUnionId();
        String avatar = newMember.getAvatar();
        MemberDO member =
                memberDao.findByOrgIdAndFieldAndAttributeAndStatus(orgId, "phone", mobile, mType, status);
        if (ObjectUtil.isEmpty(member) && StrUtil.isNotEmpty(email)) {
            member = memberDao.findByOrgIdAndFieldAndAttributeAndStatus(orgId, "email", email, mType, status);
        }
        if (ObjectUtil.isEmpty(member) && StrUtil.isNotEmpty(openId) && StrUtil.isNotEmpty(appId)) {
            member = memberDao.findByAppIdAndOpenId(orgId, mType, appId, openId);
        }
        String memberId = ObjectUtil.isNotEmpty(member) ? member.getId() : "";
        if (isSync) {
            // 分组同步令牌
            String groupSyncToken = CommonUtil.getUUID();
            if (ObjectUtil.isEmpty(member)) {
                log.info("手机题创建答卷同步个人联系人");
                // fix 个人联系人需要进行配额限制
                ServiceResult<String> result = memberUtil.checkMemberNumber(orgId);
                if (!result.isSuccess()) {
                    log.error(result.getMsg());
                } else {
                    if (StrUtil.isEmpty(gender)) {
                        // 若答卷的性别不存在 则使用微信的性别
                        if (StrUtil.isNotEmpty(wxSex)) {
                            newMember.setGender(wxSex);
                        }
                    }
                    newMember.setCreateTime(DateUtil.getCommonDate());
                    newMember.setUpdateTime(newMember.getCreateTime());
                    // 获取当前企业的个人联系人编号
                    ServiceResult<Integer> sequenceResult =
                            sequenceService.getSequence("member:memberNo_INDIVIDUAL_" + orgId, 1L);
                    String memberNo = "C" + NumberUtil.decimalFormat("00000000", sequenceResult.getData());
                    if (log.isInfoEnabled()) {
                        log.info("该联系人编号 {}", memberNo);
                    }
                    newMember.setMemberNo(memberNo);
                    // 分组同步令牌
                    newMember.setGroupSyncToken(groupSyncToken);
                    // 创建联系人
                    MemberDO saveMember = memberDao.surveySaveMember(newMember);
                    // 异步更新联系人分组信息
                    groupService.sendMemberCreationUpdMessage(orgId, saveMember.getId(), groupSyncToken);
                    memberId = saveMember.getId();
                    newMember.setId(saveMember.getId());

                    // 推送创建的联系人
                    MemberMessage message = MemberUtil.memberDoToMemberMessage(saveMember);
                    message.setOrgCode(dto.getCode());
                    message.setOrgName(dto.getName());
                    memberUtil.publishCreateMember(message);

                    // 推送成为联系人足迹点
                    JSONObject footprint = new JSONObject();
                    footprint.put("title", "成为联系人");
                    AddFootprintParam addFootprintParam = new AddFootprintParam();
                    addFootprintParam.setOrgId(orgId);
                    addFootprintParam.setMemberId(newMember.getId());
                    addFootprintParam.setType(FootprintTypeEnum.MEMBER.getIndex());
                    addFootprintParam.setSourceKey(newMember.getId());
                    addFootprintParam.setContent(footprint);
                    addFootprintParam.setFootprintTime(newMember.getCreateTime());
                    footprintService.publishFootprint(addFootprintParam);

                    // 推送联系人名片
                    sourceCardService.publishSourceCard(newMember, CardSourceTypeEnum.SURVEY.getIndex());
                }
            } else {
                log.info("手机题创建答卷更新个人联系人");
                if (StrUtil.isNotEmpty(mobile)) {
                    member.setPhone(mobile);
                }
                if (StrUtil.isNotEmpty(email)) {
                    member.setEmail(email);
                }
                if (StrUtil.isNotEmpty(name)) {
                    member.setName(name);
                }
                if (StrUtil.isNotEmpty(gender)) {
                    member.setGender(gender);
                } else {
                    if (StrUtil.isNotEmpty(wxSex)) {
                        // 只有联系人原有性别为空才更新为微信性别
                        String gender1 = member.getGender();
                        if (StrUtil.isEmpty(gender1)) {
                            member.setGender(wxSex);
                        }
                    }
                }
                if (StrUtil.isNotEmpty(address)) {
                    member.setAddress(address);
                }
                if (StrUtil.isNotEmpty(appId)) {
                    member.setAppId(appId);
                }
                if (StrUtil.isNotEmpty(openId)) {
                    member.setOpenId(openId);
                }
                if (StrUtil.isNotEmpty(nickname)) {
                    member.setNickname(nickname);
                }
                if (StrUtil.isNotEmpty(avatar)) {
                    member.setAvatar(avatar);
                }
                if (StrUtil.isNotEmpty(unionId)) {
                    member.setUnionId(unionId);
                }
                member.setUpdateTime(DateUtil.getCommonDate());
                // 分组同步令牌
                member.setGroupSyncToken(groupSyncToken);
                memberDao.updateMember(member, true);
                // 异步更新联系人分组信息
                groupService.sendMemberCreationUpdMessage(member.getOrgId(), member.getId(), member.getGroupSyncToken());

                // 推送更新的联系人
                MemberMessage message = new MemberMessage();
                BeanUtil.copyProperties(member, message);
                message.setOrgCode(dto.getCode());
                message.setOrgName(dto.getName());
                memberUtil.publishUpdateMember(message);
            }
        }
        if (StrUtil.isEmpty(respondent.getMemberId()) && StrUtil.isNotEmpty(memberId)) {
            // 更新导入问卷的联系人 答卷中没有联系人id 就把新的联系人id更新到答卷
            Respondent.Builder builder = Respondent.newBuilder();
            builder.setId(respondent.getId());
            builder.setMemberId(memberId);
            if (log.isInfoEnabled()) {
                log.info("问卷 {} 更新的联系人Id {}", respondent.getId(), memberId);
            }
            surveyClient.updateRespondent(builder.build(), respondent.getProjectId());
            this.publishMemberCreatedMessage(memberId, respondent);
        }
    }

    /**
     * 处理邮件问卷
     *
     * @param newMember
     * @param isSync
     * @param dto
     * @param respondent
     * @param wxSex
     */
    private void handleEmail(MemberDO newMember, Boolean isSync, OrganizationDTO dto, Respondent respondent, String wxSex) {
        String orgId = newMember.getOrgId();
        Integer mType = newMember.getMemberType();
        Integer status = newMember.getStatus();
        String email = newMember.getEmail();
        String name = newMember.getName();
        String gender = newMember.getGender();
        String address = newMember.getAddress();
        String openId = newMember.getOpenId();
        String appId = newMember.getAppId();
        String nickname = newMember.getNickname();
        String unionId = newMember.getUnionId();
        String avatar = newMember.getAvatar();
        MemberDO member =
                memberDao.findByOrgIdAndFieldAndAttributeAndStatus(orgId, "email", email, mType, status);
        if (ObjectUtil.isEmpty(member) && StrUtil.isNotEmpty(openId) && StrUtil.isNotEmpty(appId)) {
            member = memberDao.findByAppIdAndOpenId(orgId, mType, appId, openId);
        }
        String memberId = ObjectUtil.isNotEmpty(member) ? member.getId() : "";
        if (isSync) {
            String groupSyncToken = CommonUtil.getUUID();
            if (ObjectUtil.isEmpty(member)) {
                log.info("邮箱题创建答卷同步个人联系人");
                ServiceResult<String> result = memberUtil.checkMemberNumber(orgId);
                if (!result.isSuccess()) {
                    log.error(result.getMsg());
                } else {
                    if (StrUtil.isEmpty(gender)) {
                        // 若答卷的性别不存在 则使用微信的性别
                        if (StrUtil.isNotEmpty(wxSex)) {
                            newMember.setGender(wxSex);
                        }
                    }
                    newMember.setCreateTime(DateUtil.getCommonDate());
                    newMember.setUpdateTime(newMember.getCreateTime());
                    newMember.setId(ObjectId.next());
                    // 获取当前企业的个人联系人编号
                    ServiceResult<Integer> sequenceResult =
                            sequenceService.getSequence("member:memberNo_INDIVIDUAL_" + orgId, 1L);
                    String memberNo = "C" + NumberUtil.decimalFormat("00000000", sequenceResult.getData());
                    if (log.isInfoEnabled()) {
                        log.info("该联系人编号 {}", memberNo);
                    }
                    newMember.setMemberNo(memberNo);
                    // 分组同步令牌
                    newMember.setGroupSyncToken(groupSyncToken);
                    // 创建联系人
                    MemberDO saveMember = memberDao.surveySaveMember(newMember);
                    // 异步更新联系人分组信息
                    groupService.sendMemberCreationUpdMessage(saveMember.getOrgId(), saveMember.getId(), saveMember.getGroupSyncToken());
                    memberId = saveMember.getId();
                    newMember.setId(saveMember.getId());
                    // 推送创建的联系人
                    MemberMessage message = MemberUtil.memberDoToMemberMessage(saveMember);
                    message.setOrgCode(dto.getCode());
                    message.setOrgName(dto.getName());
                    memberUtil.publishCreateMember(message);
                    // 推送成为联系人足迹点
                    JSONObject footprint = new JSONObject();
                    footprint.put("title", "成为联系人");
                    AddFootprintParam addFootprintParam = new AddFootprintParam();
                    addFootprintParam.setOrgId(orgId);
                    addFootprintParam.setMemberId(newMember.getId());
                    addFootprintParam.setType(FootprintTypeEnum.MEMBER.getIndex());
                    addFootprintParam.setSourceKey(newMember.getId());
                    addFootprintParam.setContent(footprint);
                    addFootprintParam.setFootprintTime(newMember.getCreateTime());
                    footprintService.publishFootprint(addFootprintParam);

                    // 推送联系人名片
                    sourceCardService.publishSourceCard(newMember, CardSourceTypeEnum.SURVEY.getIndex());
                }
            } else {
                log.info("邮件题更新答卷个人联系人");
                if (StrUtil.isNotEmpty(name)) {
                    member.setName(name);
                }
                if (StrUtil.isNotEmpty(gender)) {
                    member.setGender(gender);
                } else {
                    if (StrUtil.isNotEmpty(wxSex)) {
                        // 只有联系人原有性别为空才更新为微信性别
                        String gender1 = member.getGender();
                        if (StrUtil.isEmpty(gender1)) {
                            member.setGender(wxSex);
                        }
                    }
                }
                if (StrUtil.isNotEmpty(address)) {
                    member.setAddress(address);
                }
                if (StrUtil.isNotEmpty(appId)) {
                    member.setAppId(appId);
                }
                if (StrUtil.isNotEmpty(openId)) {
                    member.setOpenId(openId);
                }
                if (StrUtil.isNotEmpty(nickname)) {
                    member.setNickname(nickname);
                }
                if (StrUtil.isNotEmpty(avatar)) {
                    member.setAvatar(avatar);
                }
                if (StrUtil.isNotEmpty(unionId)) {
                    member.setUnionId(unionId);
                }
                member.setUpdateTime(DateUtil.getCommonDate());
                // 分组同步令牌
                member.setGroupSyncToken(groupSyncToken);
                memberDao.updateMember(member, true);
                // 异步更新联系人分组信息
                groupService.sendMemberCreationUpdMessage(member.getOrgId(), member.getId(), member.getGroupSyncToken());

                // 推送更新的联系人
                MemberMessage message = new MemberMessage();
                BeanUtil.copyProperties(member, message);
                message.setOrgCode(dto.getCode());
                message.setOrgName(dto.getName());
                memberUtil.publishUpdateMember(message);
            }
        }
        if (StrUtil.isEmpty(respondent.getMemberId()) && StrUtil.isNotEmpty(memberId)) {
            // 更新导入问卷的联系人 答卷中没有联系人id 就把新的联系人id更新到答卷
            Respondent.Builder builder = Respondent.newBuilder();
            builder.setId(respondent.getId());
            builder.setMemberId(memberId);
            if (log.isInfoEnabled()) {
                log.info("问卷 {} 更新的联系人Id {}", respondent.getId(), memberId);
            }
            surveyClient.updateRespondent(builder.build(), respondent.getProjectId());
            this.publishMemberCreatedMessage(memberId, respondent);
        }
    }

    /**
     * 处理微信问卷
     *
     * @param newMember
     * @param isSync
     * @param dto
     * @param respondent
     * @param wxSex
     */
    private void handleWechat(MemberDO newMember, Boolean isSync, OrganizationDTO dto, Respondent respondent, String wxSex) {
        String orgId = newMember.getOrgId();
        Integer mType = newMember.getMemberType();
        String appId = newMember.getAppId();
        String openId = newMember.getOpenId();
        String name = newMember.getName();
        String gender = newMember.getGender();
        String address = newMember.getAddress();
        String nickname = newMember.getNickname();
        String unionId = newMember.getUnionId();
        String avatar = newMember.getAvatar();

        MemberDO member =
                memberDao.findByAppIdAndOpenId(orgId, mType, appId, openId);
        String memberId = ObjectUtil.isNotEmpty(member) ? member.getId() : "";
        if (isSync) {
            String groupSyncToken = CommonUtil.getUUID();
            if (ObjectUtil.isEmpty(member)) {
                log.info("微信答题同步个人联系人");
                ServiceResult<String> result = memberUtil.checkMemberNumber(orgId);
                if (!result.isSuccess()) {
                    log.error(result.getMsg());
                } else {
                    if (StrUtil.isEmpty(gender)) {
                        // 若答卷的性别不存在 则使用微信的性别
                        if (StrUtil.isNotEmpty(wxSex)) {
                            newMember.setGender(wxSex);
                        }
                    }
                    newMember.setCreateTime(DateUtil.getCommonDate());
                    newMember.setUpdateTime(newMember.getCreateTime());
                    newMember.setId(ObjectId.next());
                    // 获取当前企业的个人联系人编号
                    ServiceResult<Integer> sequenceResult =
                            sequenceService.getSequence("member:memberNo_INDIVIDUAL_" + orgId, 1L);
                    String memberNo = "C" + NumberUtil.decimalFormat("00000000", sequenceResult.getData());
                    if (log.isInfoEnabled()) {
                        log.info("该联系人编号 {}", memberNo);
                    }
                    newMember.setMemberNo(memberNo);
                    // 分组同步令牌
                    newMember.setGroupSyncToken(groupSyncToken);
                    // 创建联系人
                    MemberDO saveMember = memberDao.surveySaveMember(newMember);
                    // 异步更新联系人分组信息
                    groupService.sendMemberCreationUpdMessage(saveMember.getOrgId(), saveMember.getId(), saveMember.getGroupSyncToken());
                    memberId = saveMember.getId();
                    newMember.setId(saveMember.getId());
                    // 推送创建的联系人
                    MemberMessage message = MemberUtil.memberDoToMemberMessage(saveMember);
                    message.setOrgCode(dto.getCode());
                    message.setOrgName(dto.getName());
                    memberUtil.publishCreateMember(message);
                    // 推送成为联系人足迹点
                    JSONObject footprint = new JSONObject();
                    footprint.put("title", "成为联系人");
                    AddFootprintParam addFootprintParam = new AddFootprintParam();
                    addFootprintParam.setOrgId(orgId);
                    addFootprintParam.setMemberId(newMember.getId());
                    addFootprintParam.setType(FootprintTypeEnum.MEMBER.getIndex());
                    addFootprintParam.setSourceKey(newMember.getId());
                    addFootprintParam.setContent(footprint);
                    addFootprintParam.setFootprintTime(newMember.getCreateTime());
                    footprintService.publishFootprint(addFootprintParam);

                    // 推送联系人名片
                    sourceCardService.publishSourceCard(newMember, CardSourceTypeEnum.SURVEY.getIndex());
                }
            } else {
                log.info("微信答题同步个人联系人");
                if (StrUtil.isNotEmpty(name)) {
                    member.setName(name);
                }
                if (StrUtil.isNotEmpty(gender)) {
                    member.setGender(gender);
                } else {
                    if (StrUtil.isNotEmpty(wxSex)) {
                        // 只有联系人原有性别为空才更新为微信性别
                        String gender1 = member.getGender();
                        if (StrUtil.isEmpty(gender1)) {
                            member.setGender(wxSex);
                        }
                    }
                }
                if (StrUtil.isNotEmpty(address)) {
                    member.setAddress(address);
                }
                if (StrUtil.isNotEmpty(appId)) {
                    member.setAppId(appId);
                }
                if (StrUtil.isNotEmpty(openId)) {
                    member.setOpenId(openId);
                }
                if (StrUtil.isNotEmpty(nickname)) {
                    member.setNickname(nickname);
                }
                if (StrUtil.isNotEmpty(avatar)) {
                    member.setAvatar(avatar);
                }
                if (StrUtil.isNotEmpty(unionId)) {
                    member.setUnionId(unionId);
                }
                member.setUpdateTime(DateUtil.getCommonDate());
                // 分组同步令牌
                member.setGroupSyncToken(groupSyncToken);
                memberDao.updateMember(member, true);
                // 异步更新联系人分组信息
                groupService.sendMemberCreationUpdMessage(member.getOrgId(), member.getId(), member.getGroupSyncToken());

                // 推送更新的联系人
                MemberMessage message = new MemberMessage();
                BeanUtil.copyProperties(member, message);
                message.setOrgCode(dto.getCode());
                message.setOrgName(dto.getName());
                memberUtil.publishUpdateMember(message);
            }
        }
        if (StrUtil.isEmpty(respondent.getMemberId()) && StrUtil.isNotEmpty(memberId)) {
            // 更新导入问卷的联系人 答卷中没有联系人id 就把新的联系人id更新到答卷
            Respondent.Builder builder = Respondent.newBuilder();
            builder.setId(respondent.getId());
            builder.setMemberId(memberId);
            if (log.isInfoEnabled()) {
                log.info("问卷 {} 更新的联系人Id {}", respondent.getId(), memberId);
            }
            surveyClient.updateRespondent(builder.build(), respondent.getProjectId());
            this.publishMemberCreatedMessage(memberId, respondent);
        }
    }

    public void publishMemberCreatedMessage(String memberId, Respondent respondent) {
        try {
            int source = respondent.getSourceValue();
            List<Integer> supportedSources = Arrays.asList(RespondentSourceEnum.QRCODE.getIndex(),
                    RespondentSourceEnum.DEDICATED.getIndex(),
                    RespondentSourceEnum.EMBED.getIndex(),
                    RespondentSourceEnum.SAMPLE.getIndex(),
                    RespondentSourceEnum.CUSTOMLINK.getIndex());
            if (supportedSources.contains(source)) {
//
//                rabbitMessageSender.sendMsg(rabbitMqConstantConfig.getAppFanoutExchange(), null,
//                        "member.member_created_by_respondent_submit", new SequenceMessage(respondent.getSeq(), respondent.getProjectId()));
                SequenceMessage message = new SequenceMessage(respondent.getSeq(), respondent.getProjectId());
                memberMessageSendService.memberCreatedByRespondentSubmitSend(message);
            }
        } catch (Exception e) {
            EMAIL_LOG.error("【联系人】发送消息member.member_created_by_respondent_submit失败, memberId: {}, seq: {}",
                    memberId, respondent.getSeq(), e);
        }
    }

    /**
     * 获取包含联系人信息的题目gid列表
     * return {'mobile': [<list of {'gid': , 'qtype': }>], 'email': [<list of {'gid': , 'qtype': }>]}
     *
     * @param questionList
     */
    private Map<String, JSONArray> getMemberQids(List<QdesQuestionDTO> questionList) {
        if (CollectionUtil.isEmpty(questionList)) {
            return Collections.emptyMap();
        }

        Map<String, JSONArray> map = new HashMap<>();
        for (QdesQuestionDTO question : questionList) {
            String mType = this.getQuestionWithMemberInfo(question);
            if (StringUtils.isNotBlank(mType)) {
                if (!map.containsKey(mType)) {
                    map.put(mType, new JSONArray());
                }
                map.get(mType).add(question.getGid());
            }
        }

        return map;
    }

    /**
     * 判断是否题目是否含有联系人信息
     *
     * @param question
     */
    private String getQuestionWithMemberInfo(QdesQuestionDTO question) {
        String customQtype = question.getCustomQtype();

        if ("info_phone".equals(customQtype)) {
            return "mobile";
        } else if ("info_email".equals(customQtype)) {
            return "email";
        } else if ("info_username".equals(customQtype)) {
            return "name";
        } else if ("info_sex".equals(customQtype)) {
            return "gender";
        } else if ("info_age".equals(customQtype)) {
            return "age";
        } else if ("city".equals(customQtype)) {
            return "address";
        } else {
            // 无联系人信息
            return null;
        }
    }

    /**
     * 目前类型为 LinkedHashMap  ArrayList
     *
     * @param answers
     * @param gidList
     * @return
     */
    private List<Object> getMemberInfo(JSONObject answers, JSONArray gidList) {
        if (CollectionUtil.isEmpty(gidList)) {
            return Collections.emptyList();
        }
        List<Object> list = new ArrayList<>();

        for (Object gid : gidList) {
            String gidStr = String.valueOf(gid);
            if (ObjectUtil.isNull(answers.get(gidStr))) {
                continue;
            }

            String className = answers.get(gidStr).getClass().getSimpleName();
            if (Objects.equals("LinkedHashMap", className)) {
                // 地址
                JSONObject jsonObject = answers.getJSONObject(gidStr);
                if (!jsonObject.isEmpty()) {
                    Set<String> keySet = jsonObject.keySet();
                    keySet.forEach(key -> {
                        list.add(jsonObject.get(key));
                    });

                }
            }
            if (Objects.equals("ArrayList", className)) {
                JSONArray array = answers.getJSONArray(gidStr);
                if (!array.isEmpty()) {
                    list.add(array.get(0));
                } else {
                    list.add("");
                }
            }
        }
        return list;
    }
}
